﻿#include "OiPCH.hpp"

namespace Oi
{
    namespace PLScannerCore
    {
        class PLCTaskImpl : public Impl<PLCTask>
        {

        public:
            QMutex _mutex;
            bool _quit;

        public:
            std::list<std::pair<PLCTask::WriteType, Core::Values>> _wDatas;

        public:
            int _simulation;
            bool _plcEnable;

        public:
            QTimer _heartbeatTimer;
            int _heartbeatValue;
            int _heartStoptimes;

        public:
            QString _formula;
            double _width;
            double _upMaterialWidth;
            double _downMaterialWidth;
            double _upMaterialThickness;
            double _downMaterialThickness;
            double _widthWarnErr;
            double _widthErrTol;
            double _thicknessWarnErr;
            double _thicknessErrTol;
            int _definitionNum;
            QList<QPointF> _definitionList;
            int _measureType;
            int _measureNum;
            QList<double> _measureList;
            double _fixedMeasurePos;
            int _startMeasureFlag;
            int _switchEnableFlag;
            ProductParams _params;

            int _heartbeatAddr;
            int _datatimeAddr;
            int _formualAddr;
            int _widthAddr;
            int _upWidthdAddr;
            int _opThicknessAddr;
            int _opUpThicknessAddr;
            int _midThicknessAddr;
            int _drThicknessAddr;
            int _drUpThicknessAddr;
        };

        PLCTask::PLCTask(QObject* parent) 
            : QThread(parent)
        {
            OI_I(PLCTask);
            
            init();
        }

        PLCTask::~PLCTask()
        {
            OI_E(PLCTask);

            exit();
        }

        void PLCTask::init()
        {
            OI_F(PLCTask);

            d->_quit = false;
            auto settings = Core::OiSettings();

            d->_simulation = settings->value("Simulation", false).toBool();
            d->_plcEnable = settings->value("PLC/Enable", false).toBool();
            d->_measureNum = 0;
            d->_heartbeatValue = 0;
            d->_heartStoptimes = 0;
            d->_heartbeatTimer.setInterval(1000);

            connect(&d->_heartbeatTimer, &QTimer::timeout, this, &PLCTask::onHeartTimeout);
            if (d->_plcEnable)
            {
                d->_heartbeatAddr = settings->value("PLC/heartbeatAddr", 0).toInt();
                d->_datatimeAddr = settings->value("PLC/datatimeAddr", 9500).toInt();
                d->_formualAddr = settings->value("PLC/formualAddr", 9520).toInt();
                d->_widthAddr = settings->value("PLC/widthAddrAddr", 9530).toInt();
                d->_upWidthdAddr = settings->value("PLC/upWidthdAddr", 9540).toInt();
                d->_opThicknessAddr = settings->value("PLC/opThicknessAddr", 9550).toInt();
                d->_opUpThicknessAddr = settings->value("PLC/opUpThicknessAddr", 9560).toInt();
                d->_midThicknessAddr = settings->value("PLC/midThicknessAddr", 9570).toInt();
                d->_drUpThicknessAddr = settings->value("PLC/drUpThicknessAddr", 9580).toInt();
                d->_drThicknessAddr = settings->value("PLC/drThicknessAddr", 9590).toInt();


                start();
            }

            if(d->_plcEnable)
            {
                start();
            }
        }

        void PLCTask::exit()
        {
            if(isRunning())
            {
                quit();
                wait();
            }
        }

        void PLCTask::run()
        {
            OI_F(PLCTask);
            bool quit = false;
            bool ready = false;
            int action;
            WriteType wtype;
            Core::Values wValue;
            if (!d->_plcEnable)
            {
                OiWarning() << "plc enable:" << d->_plcEnable;
                return;
            }

            int reconnect = 0;
            QString deviceName = Core::OiSettings()->value("PLC/DeviceName", "PLC_0").toString();
            QString addr = Core::OiSettings()->value("PLC/Address", "192.168.0.200").toString();
            QString port = Core::OiSettings()->value("PLC/Port", "4096").toString();
//            QString args = Core::OiSettings()->value("PLC/Args", "comm=udp&frame=3E&ascii=0&network_number=0&pc_number=255").toString();
            QString args = Core::OiSettings()->value("PLC/Args", "comm=tcp&frame=3E&ascii=0&peer=0&network_number=0&pc_number=255").toString();
            
            std::string path;
            path += "protocol=melsec";
            path += "&addr=" + addr.toStdString();
            path += "&port=" + port.toStdString();
            path += "&" + args.toStdString();
            QSharedPointer<Util::PLC> _device = Util::PLCService::instance()->get(qPrintable(deviceName));

            if (_device.isNull())
            {
                _device = Util::PLC::create(qPrintable(deviceName), path.c_str());
                Util::PLCService::instance()->add(qPrintable(deviceName), _device);
            }
            if (_device->isValid())
            {
                if (_device->connect() == 0)
                {
                    ready = true;
                }
                else
                {
                    PLScannerError::instance()->reportError(PLScannerError::ERR_PLC_INVALID);
                }
            }
            else
            {
                PLScannerError::instance()->reportError(PLScannerError::ERR_PLC_INVALID);
            }
            if (!ready)
            {
                PLScannerError::instance()->reportError(PLScannerError::ERR_PLC_TIMEOUT);
                return;
            }

            while(!quit)
            {
                if (reconnect > 5)
                {
                    Util::PLCService::instance()->exit();

                    _device = Util::PLC::create(qPrintable(deviceName), path.c_str());
                    Util::PLCService::instance()->add(qPrintable(deviceName), _device);

                    if (_device->isValid())
                    {
                        if (_device->connect() == 0)
                        {
                            ready = true;
                            OiWarning() << "plc connect success!";
                        }
                        else
                        {
                            PLScannerError::instance()->reportError(PLScannerError::ERR_MODBUS_INVALID);
                        }
                    }
                    else
                    {
                        PLScannerError::instance()->reportError(PLScannerError::ERR_MODBUS_INVALID);
                    }
                }

                if (ready)
                {
                    d->_mutex.lock();
                    quit = d->_quit;
                    action = d->_wDatas.size();
                    if (action != 0)
                    {
                        wtype = d->_wDatas.front().first;
                        wValue = d->_wDatas.front().second;
                        d->_wDatas.pop_front();
                    }

                    d->_mutex.unlock();

                    if (action != 0)
                    {
                        QList<int> lstType;
                        QList<int> lstStartPos;
                        switch (wtype)
                        {
                        case PLCTask::WT_HEARTBEAT:
                        {
                            lstType.append(2);
                            lstStartPos.append(d->_heartbeatAddr);
                            writePlc(_device, lstType, lstStartPos, wValue);
                            break;
                        }
                        case PLCTask::WT_COMMAND:
                        {
                            lstType.append(2);
                            lstStartPos.append(320);
                            writePlc(_device, lstType, lstStartPos, wValue);
                            break;
                        }
                        case PLCTask::WT_DATARESULT:
                        {
                            lstType.append(9);
                            lstType.append(9);
                            lstType.append(7);
                            lstType.append(7);
                            lstType.append(7);
                            lstType.append(7);
                            lstType.append(7);
                            lstType.append(7);
                            lstType.append(7);
                            lstStartPos.append(d->_datatimeAddr);
                            lstStartPos.append(d->_formualAddr);
                            lstStartPos.append(d->_widthAddr);
                            lstStartPos.append(d->_upWidthdAddr);
                            lstStartPos.append(d->_opThicknessAddr);
                            lstStartPos.append(d->_opUpThicknessAddr);
                            lstStartPos.append(d->_midThicknessAddr);
                            lstStartPos.append(d->_drUpThicknessAddr);
                            lstStartPos.append(d->_drThicknessAddr);
                            writePlc(_device, lstType, lstStartPos, wValue);
                            break;
                        }

                        default:
                            break;
                        }
                        QThread::msleep(10);
                    }
                    else
                    {                      
                        QString specName;
                        QList<uint16_t> blstValues;
                        //读取规格号     d2000-->d2009
//                        readPlc(_device, 2000, 10, specName);

                        _device->appendTag("D", 11, 0, 1);
                        _device->pull("D");
                        std::string recvData;
                        if (_device->get("D", recvData, 2000, 100) == 0)
                        {
                            specName = QString::fromStdString(recvData);
                            specName.truncate(specName.indexOf(QChar::Null));
                            //specName = specName.mid(0,7);
                        }
                        else
                        {
                            OiWarning() << "error:";
                        }
                        blstValues.clear();
                       
                        //读取下层料宽
                        short upMateriaWidth = 0;
                        short downMateriaWidth = 0;
                        short upMateriaThickness = 0;
                        short downMateriaThickness = 0;
                        readPlc(_device, 2020, 1, blstValues);
                        if (blstValues.size() >= 1)
                            downMateriaWidth = blstValues[0];
                        //读取上层料宽
                        blstValues.clear();
                        readPlc(_device, 2024, 1, blstValues);
                        if (blstValues.size() >= 1)
                        {
                             upMateriaWidth = blstValues[0];
                        }
                        blstValues.clear();
                        readPlc(_device, 2030, 1, blstValues);
                        if (blstValues.size() >= 1)
                        {
                            downMateriaThickness = (short)blstValues[0];
                        }

                        blstValues.clear();
                        readPlc(_device, 2034, 1, blstValues);
                        if (blstValues.size() >= 1)
                        {
                            upMateriaThickness = (short)blstValues[0];
                        }
                       
                        d->_mutex.lock();

                        d->_formula = specName;
                        d->_upMaterialThickness = upMateriaThickness;
                        d->_downMaterialThickness = downMateriaThickness;
                        d->_upMaterialWidth = upMateriaWidth;
                        d->_downMaterialWidth = downMateriaWidth;
                        d->_mutex.unlock();
                        QThread::msleep(10);
                    }
                }
                QThread::msleep(50);
            }

            Util::PLCService::instance()->exit();
        }

        void PLCTask::quit()
        {
            OI_F(PLCTask);

            setHeartbeatEnable(false);

            QMutexLocker lock(&d->_mutex);
            d->_quit = true;

            QThread::quit();
        }

        void PLCTask::start()
        {
            OI_F(PLCTask);
            d->_mutex.lock();
            d->_quit = false;
            d->_wDatas.clear();
            d->_mutex.unlock();
            QThread::start();
        }

        void PLCTask::setHeartbeatEnable(bool enable)
        {
            OI_F(PLCTask);
            if (enable)
            {
                d->_heartbeatTimer.start();
            }
            else
            {
                d->_heartbeatTimer.stop();
            }
        }

        void PLCTask::writeResult(const int& result)
        {
            OI_F(PLCTask);
            QMutexLocker lock(&d->_mutex);
            Core::Values wValue;
            wValue.push_back(Core::Value(result));
            d->_wDatas.push_back(std::make_pair(WT_RESULT, wValue));
        }

        void PLCTask::writeResult(DataRow data)
        {
            OI_F(PLCTask);
            QMutexLocker lock(&d->_mutex);
            Core::Values wValue;
            wValue.push_back(Core::Value(data.datetime.toString("yyyy-MM-dd HH:mm:ss")));
            wValue.push_back(Core::Value(data.formula));
            wValue.push_back(Core::Value(data.width));
            wValue.push_back(Core::Value(data.widthEl));
            wValue.push_back(Core::Value(data.thickness1));
            wValue.push_back(Core::Value(data.thickness2));
            wValue.push_back(Core::Value(data.thickness3));
            wValue.push_back(Core::Value(data.thickness4));
            wValue.push_back(Core::Value(data.thickness5));
            d->_wDatas.push_back(std::make_pair(WT_DATARESULT, wValue));
        }

        void PLCTask::setDetectionState(const int& state)
        {
            OI_F(PLCTask);
            QMutexLocker lock(&d->_mutex);
            Core::Values wValue;
            wValue.push_back(Core::Value(state));
            d->_wDatas.push_back(std::make_pair(WT_COMMAND, wValue));
        }

        void PLCTask::writePlc(QSharedPointer<Util::PLC> device, QList<int> lstType, QList<int> lstStartPos, Core::Values lstValues)
        {
            Core::Values result;
            
            for (int i = 0; i < lstType.size(); i++)
            {
                QByteArray sendName = "D";

                int sendType = lstType[i];
                int sendStart = lstStartPos[i];
                int sendCount = 1;
                switch (sendType)
                {
                case 0:
                {
                    auto values = lstValues[i].value<Core::Values>();

                    if (values.isEmpty())
                    {
                        result << Core::Value(false); continue;
                    }

                    int sendCount = values.size();

                    device->appendTag(sendName, 0, 1, sendCount);
                    std::vector<int8_t> sendData(sendCount);
                    for (int j = 0; j < values.size(); j++)
                    {
                        sendData[j] = values[j].value<int>();
                    }
                    if (device->set(sendName, sendData.data(), sendStart, sendCount) == 0)
                    {
                        result << Core::Value(true);
                    }
                    else
                    {
                        result << Core::Value(false);
                    }
                    break;
                }

                case 2:
                {
                    auto values = lstValues[i].value<Core::Values>();

                    if (values.isEmpty())
                    {
                        result << Core::Value(false); continue;
                    }
                    device->appendTag(sendName, 4, 2, sendCount);
                    std::vector<uint16_t> sendData(sendCount);
                    for (int j = 0; j < values.size(); j++)
                    {
                        sendData[j] = values[j].value<uint16_t>();
                    }
                    if (device->set(sendName, sendData.data(), sendStart, sendCount) == 0)
                    {
                        result << Core::Value(true);
                    }
                    else
                    {
                        result << Core::Value(false);
                    }
                    break;
                }
                case 7:
                {
                    float sendData = lstValues[i].value<float>();

                    int sendStart = lstStartPos[i];
                   
                    device->appendTag(sendName, 9, 4, sendCount);
                    if (device->set(sendName, &sendData, sendStart, sendCount) == 0)
                    {
                        result << Core::Value(true);
                    }
                    else
                    {
                        result << Core::Value(false);
                    }
                    break;
                }
                case 9:
                {
                    auto sendData = lstValues[i].value<QString>().toStdString();
                    int sendStart = lstStartPos[i];
                    int sendBytes = sendData.size();

                    device->appendTag(sendName, 11, 0, 1);

                    if (device->set(sendName, sendData, sendStart, sendBytes) == 0)
                    {
                        result << Core::Value(true);
                    }
                    else
                    {
                        result << Core::Value(false);
                    }
                    break;
                }
                }

                if (device->push(sendName) != 0)
                {
                    OiWarning() << "PLC写入超时！";
                }
            }
        }

        void PLCTask::readPlc(QSharedPointer<Util::PLC> device, int beginPos, int counts, QList<uint16_t>& slstValue, int type)
        {
            OI_F(PLCTask);
            Core::Values values;
            Core::Values result;
            QList<QByteArray> recvNames;
            QList<int> recvTypes;
            QList<int> recvStarts;
            QList<int> recvCounts;
            recvNames << "D";
            for (int index = beginPos;index < beginPos + counts; index++)
            {
                recvTypes << type;
                recvStarts << index;
            }

            for (int i = 0; i < recvTypes.size(); i++)
            {
                QByteArray recvName = recvNames[0];

                int recvCount = recvCounts.size() > i ? recvCounts[i] : 1;

                Core::Values nodes;

                if (recvCount == 0)
                {
                    continue;
                }

                switch (recvTypes[i])
                {
                case 0:
                {
                    device->appendTag(recvName, 0, 1, recvCount);
                    break;
                }
                case 1:
                {
                    device->appendTag(recvName, 3, 2, recvCount);
                    break;
                }
                case 2:
                {
                    device->appendTag(recvName, 4, 2, recvCount);
                    break;
                }
                case 3:
                {
                    device->appendTag(recvName, 5, 4, recvCount);
                    break;
                }
                case 4:
                {
                    device->appendTag(recvName, 6, 4, recvCount);
                    break;
                }
                case 5:
                {
                    device->appendTag(recvName, 7, 8, recvCount);
                    break;
                }
                case 6:
                {
                    device->appendTag(recvName, 8, 8, recvCount);
                    break;
                }
                case 7:
                {
                    device->appendTag(recvName, 9, 4, recvCount);
                    break;
                }
                case 8:
                {
                    device->appendTag(recvName, 10, 8, recvCount);
                    break;
                }
                case 9:
                {
                    device->appendTag(recvName, 11, 0, 1);
                    break;
                }
                case 10:
                {
                    device->appendTag(recvName, 11, 0, recvCount);
                    break;
                }
                }

                if (device->pull(recvName) != 0)
                {
                    OiWarning() << "PLC读取超时: " << recvName;
                }
            }
            for (int i = 0; i < recvTypes.size(); i++)
            {
                QByteArray recvName = recvNames[0];

                int recvStart = recvStarts.size() > i ? recvStarts[i] : 0;
                int recvCount = 1;

                Core::Values nodes;

                if (recvCount == 0)
                {
                    values << Core::Value::from(nodes);
                    result << Core::Value::from(false);
                    continue;
                }

                switch (recvTypes[i])
                {
                case 0:
                {
                    std::vector<int8_t> recvData(recvCount);
                    if (device->get(recvName, recvData.data(), recvStart, recvCount) == 0)
                    {
                        for (int i = 0; i < recvCount; i++)
                        {
                            int8_t base = 0x01;
                            for (int b = 0; b < 8; b++)
                            {
                                if (recvData[i] & base)
                                {
                                    nodes << Core::Value::from(true);
                                }
                                else
                                {
                                    nodes << Core::Value::from(false);
                                }
                                base = base << 1;
                            }
                        }
                        result << Core::Value::from(true);
                    }
                    else
                    {
                        result << Core::Value::from(false);
                    }
                    break;
                    /*std::vector<int8_t> recvData(recvCount);
                    if (device->get(recvName, recvData.data(), recvStart, recvCount) == 0)
                    {
                        for (int i = 0; i < recvCount; i++)
                        {
                            int8_t base = 0x01;
                            for (int b = 0; b < 8; b++)
                            {
                                if (recvData[i] & base)
                                {
                                    nodes << Core::Value::from(true);
                                }
                                else
                                {
                                    nodes << Core::Value::from(false);
                                }

                                base = base << 1;
                            }

                        }
                        result << Core::Value::from(true);
                    }
                    break;*/
                }
                case 1:
                {
                    std::vector<int16_t> recvData(recvCount);
                    if (device->get(recvName, recvData.data(), recvStart, recvCount) == 0)
                    {
                        for (int i = 0; i < recvCount; i++)
                        {
                            nodes << Core::Value::from(recvData[i]);
                        }
                        result << Core::Value::from(true);
                    }
                    else
                    {
                        result << Core::Value::from(false);
                    }
                    break;
                }
                case 2:
                {
                    std::vector<uint16_t> recvData(recvCount);
                    if (device->get(recvName, recvData.data(), recvStart, recvCount) == 0)
                    {
                        for (int i = 0; i < recvCount; i++)
                        {
                            nodes << Core::Value::from(recvData[i]);
                        }
                        result << Core::Value::from(true);
                    }
                    else
                    {
                        result << Core::Value::from(false);
                    }
                    break;
                }
                case 3:
                {
                    std::vector<int32_t> recvData(recvCount);
                    if (device->get(recvName, recvData.data(), recvStart, recvCount) == 0)
                    {
                        for (int i = 0; i < recvCount; i++)
                        {
                            nodes << Core::Value::from(recvData[i]);
                        }
                        result << Core::Value::from(true);
                    }
                    else
                    {
                        result << Core::Value::from(false);
                    }
                    break;
                }
                case 4:
                {
                    std::vector<uint32_t> recvData(recvCount);
                    if (device->get(recvName, recvData.data(), recvStart, recvCount) == 0)
                    {
                        for (int i = 0; i < recvCount; i++)
                        {
                            nodes << Core::Value::from(recvData[i]);
                        }
                        result << Core::Value::from(true);
                    }
                    else
                    {
                        result << Core::Value::from(false);
                    }
                    break;
                }
                case 5:
                {
                    std::vector<int64_t> recvData(recvCount);
                    if (device->get(recvName, recvData.data(), recvStart, recvCount) == 0)
                    {
                        for (int i = 0; i < recvCount; i++)
                        {
                            nodes << Core::Value::from(recvData[i]);
                        }
                        result << Core::Value::from(true);
                    }
                    else
                    {
                        result << Core::Value::from(false);
                    }
                    break;
                }
                case 6:
                {
                    std::vector<uint64_t> recvData(recvCount);
                    if (device->get(recvName, recvData.data(), recvStart, recvCount) == 0)
                    {
                        for (int i = 0; i < recvCount; i++)
                        {
                            nodes << Core::Value::from(recvData[i]);
                        }
                        result << Core::Value::from(true);
                    }
                    else
                    {
                        result << Core::Value::from(false);
                    }
                    break;
                }
                case 7:
                {
                    std::vector<float> recvData(recvCount);
                    if (device->get(recvName, recvData.data(), recvStart, recvCount) == 0)
                    {
                        for (int i = 0; i < recvCount; i++)
                        {
                            nodes << Core::Value::from(recvData[i]);
                        }
                        result << Core::Value::from(true);
                    }
                    else
                    {
                        result << Core::Value::from(false);
                    }
                    break;
                }
                case 8:
                {
                    std::vector<double> recvData(recvCount);
                    if (device->get(recvName, recvData.data(), recvStart, recvCount) == 0)
                    {
                        for (int i = 0; i < recvCount; i++)
                        {
                            nodes << Core::Value::from(recvData[i]);
                        }
                        result << Core::Value::from(true);
                    }
                    else
                    {
                        result << Core::Value::from(false);
                    }
                    break;
                }
                case 9:
                {
                    std::string recvData;
                    if (device->get(recvName, recvData, recvStart, recvCount) == 0)
                    {
                        nodes << Core::Value::from(QString::fromStdString(recvData));
                        result << Core::Value::from(true);
                    }
                    else
                    {
                        result << Core::Value::from(false);
                    }
                    break;
                }
                case 10:
                {
                    std::vector<std::string> recvData(recvCount);
                    if (device->get(recvName, recvData.data(), recvStart, recvCount) == 0)
                    {
                        for (int i = 0; i < recvCount; i++)
                        {
                            nodes << Core::Value::from(QString::fromStdString(recvData[i]));
                        }
                        result << Core::Value::from(true);
                    }
                    else
                    {
                        result << Core::Value::from(false);
                    }
                    break;
                }
                }

                values << Core::Value::from(nodes);
            }
            for (int index = 0; index < counts;index++)
            {
                slstValue.append(values[index].value<Core::Values>()[0].toUInt());
            }
        }

        void PLCTask::readPlc(QSharedPointer<Util::PLC> device, int beginPos, int counts, QList<int>& slstValue, int type)
        {
            OI_F(PLCTask);
            Core::Values values;
            Core::Values result;
            QList<QByteArray> recvNames;
            QList<int> recvTypes;
            QList<int> recvStarts;
            QList<int> recvCounts;
            recvNames << "D";

            for (int index = beginPos; index < beginPos + counts; index++)
            {
                recvTypes << type;
                recvStarts << index;
            }

            for (int i = 0; i < recvTypes.size(); i++)
            {
                QByteArray recvName = recvNames[0];

                int recvCount = recvCounts.size() > i ? recvCounts[i] : 1;

                Core::Values nodes;

                if (recvCount == 0)
                {
                    continue;
                }

                switch (recvTypes[i])
                {
                case 0:
                {
                    device->appendTag(recvName, 0, 1, recvCount);
                    break;
                }
                case 1:
                {
                    device->appendTag(recvName, 3, 2, recvCount);
                    break;
                }
                case 2:
                {
                    device->appendTag(recvName, 4, 2, recvCount);
                    break;
                }
                case 3:
                {
                    device->appendTag(recvName, 5, 4, recvCount);
                    break;
                }
                case 4:
                {
                    device->appendTag(recvName, 6, 4, recvCount);
                    break;
                }
                case 5:
                {
                    device->appendTag(recvName, 7, 8, recvCount);
                    break;
                }
                case 6:
                {
                    device->appendTag(recvName, 8, 8, recvCount);
                    break;
                }
                case 7:
                {
                    device->appendTag(recvName, 9, 4, recvCount);
                    break;
                }
                case 8:
                {
                    device->appendTag(recvName, 10, 8, recvCount);
                    break;
                }
                case 9:
                {
                    device->appendTag(recvName, 11, 0, 1);
                    break;
                }
                case 10:
                {
                    device->appendTag(recvName, 11, 0, recvCount);
                    break;
                }
                }

                if (device->pull(recvName) != 0)
                {
                    OiWarning() << "PLC读取超时: " << recvName;
                }
            }
            for (int i = 0; i < recvTypes.size(); i++)
            {
                QByteArray recvName = recvNames[0];

                int recvStart = recvStarts.size() > i ? recvStarts[i] : 0;
                int recvCount = 1;

                Core::Values nodes;

                if (recvCount == 0)
                {
                    values << Core::Value::from(nodes);
                    result << Core::Value::from(false);
                    continue;
                }

                switch (recvTypes[i])
                {
                case 0:
                {
                    std::vector<int8_t> recvData(recvCount);
                    if (device->get(recvName, recvData.data(), recvStart, recvCount) == 0)
                    {
                        for (int i = 0; i < recvCount; i++)
                        {
                            int8_t base = 0x01;
                            for (int b = 0; b < 8; b++)
                            {
                                if (recvData[i] & base)
                                {
                                    nodes << Core::Value::from(true);
                                }
                                else
                                {
                                    nodes << Core::Value::from(false);
                                }
                                base = base << 1;
                            }
                        }
                        result << Core::Value::from(true);
                    }
                    else
                    {
                        result << Core::Value::from(false);
                    }
                    break;
                    /*std::vector<int8_t> recvData(recvCount);
                    if (device->get(recvName, recvData.data(), recvStart, recvCount) == 0)
                    {
                        for (int i = 0; i < recvCount; i++)
                        {
                            int8_t base = 0x01;
                            for (int b = 0; b < 8; b++)
                            {
                                if (recvData[i] & base)
                                {
                                    nodes << Core::Value::from(true);
                                }
                                else
                                {
                                    nodes << Core::Value::from(false);
                                }

                                base = base << 1;
                            }

                        }
                        result << Core::Value::from(true);
                    }
                    break;*/
                }
                case 1:
                {
                    std::vector<int16_t> recvData(recvCount);
                    if (device->get(recvName, recvData.data(), recvStart, recvCount) == 0)
                    {
                        for (int i = 0; i < recvCount; i++)
                        {
                            nodes << Core::Value::from(recvData[i]);
                        }
                        result << Core::Value::from(true);
                    }
                    else
                    {
                        result << Core::Value::from(false);
                    }
                    break;
                }
                case 2:
                {
                    std::vector<uint16_t> recvData(recvCount);
                    if (device->get(recvName, recvData.data(), recvStart, recvCount) == 0)
                    {
                        for (int i = 0; i < recvCount; i++)
                        {
                            nodes << Core::Value::from(recvData[i]);
                        }
                        result << Core::Value::from(true);
                    }
                    else
                    {
                        result << Core::Value::from(false);
                    }
                    break;
                }
                case 3:
                {
                    std::vector<int32_t> recvData(recvCount);
                    if (device->get(recvName, recvData.data(), recvStart, recvCount) == 0)
                    {
                        for (int i = 0; i < recvCount; i++)
                        {
                            nodes << Core::Value::from(recvData[i]);
                        }
                        result << Core::Value::from(true);
                    }
                    else
                    {
                        result << Core::Value::from(false);
                    }
                    break;
                }
                case 4:
                {
                    std::vector<uint32_t> recvData(recvCount);
                    if (device->get(recvName, recvData.data(), recvStart, recvCount) == 0)
                    {
                        for (int i = 0; i < recvCount; i++)
                        {
                            nodes << Core::Value::from(recvData[i]);
                        }
                        result << Core::Value::from(true);
                    }
                    else
                    {
                        result << Core::Value::from(false);
                    }
                    break;
                }
                case 5:
                {
                    std::vector<int64_t> recvData(recvCount);
                    if (device->get(recvName, recvData.data(), recvStart, recvCount) == 0)
                    {
                        for (int i = 0; i < recvCount; i++)
                        {
                            nodes << Core::Value::from(recvData[i]);
                        }
                        result << Core::Value::from(true);
                    }
                    else
                    {
                        result << Core::Value::from(false);
                    }
                    break;
                }
                case 6:
                {
                    std::vector<uint64_t> recvData(recvCount);
                    if (device->get(recvName, recvData.data(), recvStart, recvCount) == 0)
                    {
                        for (int i = 0; i < recvCount; i++)
                        {
                            nodes << Core::Value::from(recvData[i]);
                        }
                        result << Core::Value::from(true);
                    }
                    else
                    {
                        result << Core::Value::from(false);
                    }
                    break;
                }
                case 7:
                {
                    std::vector<float> recvData(recvCount);
                    if (device->get(recvName, recvData.data(), recvStart, recvCount) == 0)
                    {
                        for (int i = 0; i < recvCount; i++)
                        {
                            nodes << Core::Value::from(recvData[i]);
                        }
                        result << Core::Value::from(true);
                    }
                    else
                    {
                        result << Core::Value::from(false);
                    }
                    break;
                }
                case 8:
                {
                    std::vector<double> recvData(recvCount);
                    if (device->get(recvName, recvData.data(), recvStart, recvCount) == 0)
                    {
                        for (int i = 0; i < recvCount; i++)
                        {
                            nodes << Core::Value::from(recvData[i]);
                        }
                        result << Core::Value::from(true);
                    }
                    else
                    {
                        result << Core::Value::from(false);
                    }
                    break;
                }
                case 9:
                {
                    std::string recvData;
                    if (device->get(recvName, recvData, recvStart, recvCount) == 0)
                    {
                        nodes << Core::Value::from(QString::fromStdString(recvData));
                        result << Core::Value::from(true);
                    }
                    else
                    {
                        result << Core::Value::from(false);
                    }
                    break;
                }
                case 10:
                {
                    std::vector<std::string> recvData(recvCount);
                    if (device->get(recvName, recvData.data(), recvStart, recvCount) == 0)
                    {
                        for (int i = 0; i < recvCount; i++)
                        {
                            nodes << Core::Value::from(QString::fromStdString(recvData[i]));
                        }
                        result << Core::Value::from(true);
                    }
                    else
                    {
                        result << Core::Value::from(false);
                    }
                    break;
                }
                }

                values << Core::Value::from(nodes);
            }

            for (int index = 0; index < counts; index++)
            {
                slstValue.append(values[index].value<Core::Values>()[0].toUInt());
            }
        }

        void PLCTask::readPlc(QSharedPointer<Util::PLC> device, int beginPos, int counts, QString& str, int type)
        {
            OI_F(PLCTask);
            Core::Values values;
            Core::Values result;
            QList<QByteArray> recvNames;
            QList<int> recvTypes;
            QList<int> recvStarts;
            QList<int> recvCounts;
            recvNames << "D";

            for (int i = 0; i < recvTypes.size(); i++)
            {
                QByteArray recvName = recvNames[0];

                int recvCount = recvCounts.size() > i ? recvCounts[i] : 1;

                Core::Values nodes;

                if (recvCount == 0)
                {
                    continue;
                }

                switch (recvTypes[i])
                {

                case 9:
                {
                    device->appendTag(recvName, 11, 0, 1);
                    break;
                }
                case 10:
                {
                    device->appendTag(recvName, 11, 0, recvCount);
                    break;
                }
                }

                if (device->pull(recvName) != 0)
                {
                    OiWarning() << "PLC读取超时: " << recvName;
                }
            }
            for (int i = 0; i < recvTypes.size(); i++)
            {
                QByteArray recvName = recvNames[0];

                int recvStart = recvStarts.size() > i ? recvStarts[i] : 0;
                int recvCount = 10;

                Core::Values nodes;

                if (recvCount == 0)
                {
                    values << Core::Value::from(nodes);
                    result << Core::Value::from(false);
                    continue;
                }

                switch (recvTypes[i])
                {
                case 9:
                {
                    std::string recvData;
                    if (device->get(recvName, recvData, recvStart, recvCount) == 0)
                    {
                        OiWarning() << "recvData:" << QString::fromStdString(recvData);
                        nodes << Core::Value::from(QString::fromStdString(recvData));
                        result << Core::Value::from(true);
                    }
                    else
                    {
                        result << Core::Value::from(false);
                    }
                    break;
                }
                case 10:
                {
                    std::vector<std::string> recvData(recvCount);
                    if (device->get(recvName, recvData.data(), recvStart, recvCount) == 0)
                    {
                        for (int i = 0; i < recvCount; i++)
                        {
                            nodes << Core::Value::from(QString::fromStdString(recvData[i]));
                        }
                        result << Core::Value::from(true);
                    }
                    else
                    {
                        result << Core::Value::from(false);
                    }
                    break;
                }
                }

                values << Core::Value::from(nodes);
            }
            for (int index = 0; index < counts; index++)
            {
                OiWarning() <<"str "<< values[index].value<Core::Values>()[0].toString();
                str.append(values[index].value<Core::Values>()[0].toString());
            }
            OiWarning() << "strFormual: " << str;
        }

        QString PLCTask::qsintToASCIIString(int val)
        {
            QString strVal = QString::number(val, 16);
            QString tmp;
            QStringList strDatas;
            for (int len = 0; len < strVal.length(); len++)
            {
                tmp += strVal[len];
                if (len % 2)
                {
                    strDatas.append(tmp);
                    tmp = "";
                }
            }
           QString ASCII_value;
            for (int i = strDatas.size() - 1; i >= 0; i--)
            {
                bool bok;
                int dec = strDatas[i].toInt(&bok, 16);
                char st = dec;
                ASCII_value.append(st);
            }
            return ASCII_value;
        }

        bool PLCTask::readSpecName(QString& name)
        {
            OI_F(PLCTask);

            QString formula;

            d->_mutex.lock();
            formula = d->_formula;
            d->_mutex.unlock();

            if (formula.isEmpty())
            {
                OiWarning() << "配方名为空，配方切换不启动";
                return false;
            }

            name = formula;
            return true;
        }

        bool PLCTask::readParams(ProductParams& params)
        {
            OI_F(PLCTask);
#if _DEBUG
            if (d->_measureNum < 50)
            {
                d->_upMaterialThickness = 50;
                d->_downMaterialThickness = 100;
                d->_downMaterialWidth = 400;
                d->_upMaterialWidth = 365;
                d->_formula = "FY24466";
                if (d->_measureNum > 200)
                {
                    d->_measureNum = 0;
                }
            }
            else
            {
                d->_upMaterialThickness = 90;
                d->_downMaterialThickness = 140;
                d->_downMaterialWidth = 420;
                d->_upMaterialWidth = 382;
                d->_formula = "FY2WF39";
                d->_measureNum++;
            }
#endif
            QString formula;
            double width = 0.0;
            double thickness;
            double widthWarnErr;
            double widthErrTol;
            double thicknessWarnErr;
            double thicknessErrTol;
            int definitionNum;
            QList<QPointF> definitionList;
            int measureType;
            QList<double> measureList;
            double fixedMeasurePos;
            double upMaterialThickness = d->_upMaterialThickness /100;
            double downMaterialThickness = d->_downMaterialThickness / 100;
          
            d->_mutex.lock();
            formula = d->_formula;
            width = d->_downMaterialWidth;
            widthWarnErr = 3;
            thickness = downMaterialThickness;
            
           
            widthErrTol = 5;
            thicknessWarnErr = 0.2;
            thicknessErrTol = 0.3;
            definitionNum = d->_definitionNum;
            QPointF definePoint(d->_upMaterialWidth/2,upMaterialThickness + downMaterialThickness);
            definitionList.append(definePoint);
            measureType = 1;
            int measurePoint1 = -((d->_downMaterialWidth - d->_upMaterialWidth)/4 + d->_upMaterialWidth /2);
            int measurePoint2 = -(d->_upMaterialWidth / 4);
            int measurePoint3 = 0;
            int measurePoint4 = d->_upMaterialWidth / 4;
            int measurePoint5 = (d->_downMaterialWidth - d->_upMaterialWidth) / 4 + d->_upMaterialWidth / 2;
            measureList.append(measurePoint1);
            measureList.append(measurePoint2);
            measureList.append(measurePoint3);
            measureList.append(measurePoint4);
            measureList.append(measurePoint5);
            fixedMeasurePos = 0;
            d->_mutex.unlock();

            if (width == 0.0 || formula.isEmpty())
            {
                OiWarning() << "<width = " << width << ",formula = " << formula << ">,配方切换不启动";
                return false;
            }

            QList<DefinitionPoint> definitionPoints;
            for (auto dpp : definitionList)
            {
                DefinitionPoint dp;
                dp.distance = fabs(dpp.x());
                dp.type = DT_HalfWidth;
                if (dpp.x() <= 0)
                {
                    dp.thicknessLeft = fabs(dpp.y());
                    dp.thicknessRight = 0.0;
                }
                else
                {
                    dp.thicknessLeft = dpp.y();
                    dp.thicknessRight = fabs(downMaterialThickness);
                }
                definitionPoints.append(dp);
            }
            params = ProductParams(formula, width, d->_upMaterialWidth, thickness, measureType
                , definitionPoints
                , measureList
                , fixedMeasurePos
                , widthErrTol
                , widthWarnErr
                , thicknessErrTol
                , thicknessWarnErr);
            params.definitionPoints = definitionPoints;
            params.materialsUpWidth = d->_upMaterialWidth;
            params.fixedPoint = QPointF(fixedMeasurePos, upMaterialThickness + downMaterialThickness);
            params.measureThickness.clear();
            params.measureThickness.append(QPointF(measurePoint1, downMaterialThickness));
            params.measureThickness.append(QPointF(measurePoint2, upMaterialThickness + downMaterialThickness));
            params.measureThickness.append(QPointF(measurePoint3, upMaterialThickness + downMaterialThickness));
            params.measureThickness.append(QPointF(measurePoint4, upMaterialThickness + downMaterialThickness));
            params.measureThickness.append(QPointF(measurePoint5, downMaterialThickness));
            params.profiles.clear();
            QList<QPointF> profile;
            profile.append(QPointF(-d->_downMaterialWidth/2,0));
            profile.append(QPointF(-d->_downMaterialWidth/2, downMaterialThickness));
            profile.append(QPointF(-d->_upMaterialWidth / 2, downMaterialThickness));
            profile.append(QPointF(-d->_upMaterialWidth / 2, downMaterialThickness + upMaterialThickness));
            profile.append(QPointF(d->_upMaterialWidth / 2, downMaterialThickness + upMaterialThickness));
            profile.append(QPointF(d->_upMaterialWidth / 2, downMaterialThickness));
            profile.append(QPointF(d->_downMaterialWidth / 2, downMaterialThickness));
            profile.append(QPointF(d->_downMaterialWidth / 2, 0));
            params.profiles.append(profile);
            if (d->_params != params)
            {
//                OiWarning() << "spacName: " << d->_formula << "  _upMaterialThickness: " << upMaterialThickness << "  _downMaterialThickness: " << downMaterialThickness <<  "  _downMaterialWidth: " << d->_downMaterialWidth << "  _upMaterialWidth: " << d->_upMaterialWidth;
            }
            return true;
        }

        void PLCTask::onHeartTimeout()
        {
            OI_F(PLCTask);

            if (d->_simulation || !d->_plcEnable)
            {
                return;
            }

            if (d->_heartbeatValue == 0)
            {
                d->_heartbeatValue = 1;
            }
            else if (d->_heartbeatValue == 1)
            {
                d->_heartbeatValue = 0;
            }
            else
            {
                d->_heartStoptimes++;
                if (d->_heartStoptimes > 30)
                {
                    OiWarning() << "PLC 通信异常";
                }
            }
            QMutexLocker lock(&d->_mutex);
            Core::Values wValue;
            wValue.push_back(Core::Value(d->_heartbeatValue));
            d->_wDatas.push_back(std::make_pair(WT_HEARTBEAT, wValue));
        }

        PLCTask* PLCTask::instance()
        {
            static PLCTask s_plc;
            return &s_plc;
        }

    }
}